﻿
// 自动演示类
function Autopilot() {
	var timer = 0;	// 定时器
	var pos0 = 0;	// 数据起始位置
	var pos = pos0;	// 当前位置
	var fram = 0;	// 当前命令帧计数
	var cmd;	// 当前命令号
	var focu = document.getElementById("focus");	// 重力感应框
	var promp = document.getElementById("prompt");	// 动态提示框
	var btnGo = document.getElementById("go");
	var objstep = document.getElementById("stepbystep");
	var poslist = new Array();	// 关键帧位置列表
	var pauseData;	// 暂停时的数据
	var stepnum = 0;	// 当前在第几步，从0开始

	var me = this;

	var prompts = [	// 提示信息
		"当横线移到后视镜下方时，向右打满",
		"车身延长线与库角接近时适当回轮",
		"车尾过库角后再向右打满",
		"车库前边线移动到后视镜下方时停车",
		"",
		"当车头接近7米线时左转弯",
		"",
		"当横线移到后视镜下方时，向左打满",
		"车身延长线与库角接近时适当回轮",
		"车尾过库角后再向左打满",
		"车库前边线移动到后视镜下方时停车",
		"",
		"当车头接近7米线时右转弯",
		"",
	];

	var stepprompts = [	// 步骤
	"1. 右侧倒车入库",
	"2. 左侧出库",
	"3. 左侧倒车入库",
	"4. 右侧出库",
	];

    var data = [	// 演示数据

		0, 5, 32, 3, 212, 254, 0, 0, 0, 0,	// 设置起始点，30帧，x 900, y -300, 车身角度 0，车轮角度 0
		20, 60,		// 倒车
		5, 30, 255, 0, 262, 1, 0,	// 5, f, x1,x2, y1, y2, n: 5提示；f帧数，x1,x2 圈点中心位置；n提示号。
		15, 65,	// 向右打方向盘65帧
		5, 30, 95, 3, 192, 1, 1,	// 5, f, x1,x2, y1, y2, n: 5提示；f帧数，x1,x2 圈点中心位置；n提示号。
		10, 17,	// 适当回轮
		5, 30, 84, 3, 202, 1, 2,	// 5, f, x1,x2, y1, y2, n: 5提示；f帧数，x1,x2 圈点中心位置；n提示号。
		15, 33,	// 向右打方向盘120帧
		10, 25,		// 向左打方向盘38帧，回正
		20, 32,		// 倒车
		5, 30, 227, 0, 255, 1, 3,	// 5, f, x1,x2, y1, y2, n: 5提示；f帧数，x1,x2 圈点中心位置；n提示号。

		0, 5, 0, 0, 94, 1, 124, 252, 0, 0,	// 设置起始点，30帧，x 0, y 350, 车身角度 -90，车轮角度 0
		22, 42,		// 向前走40帧
		5, 30, 180, 1, 235, 0, 5,	// 5, f, x1,x2, y1, y2, n: 5提示；f帧数，x1,x2 圈点中心位置；n提示号。
		10, 104,		// 向左打方向盘120帧
		15, 25,		// 向右打方向盘38帧，回正
		22, 67,		// 向前走40帧

		0, 5, 224, 252, 212, 254, 8, 7, 0, 0,	// 设置起始点，30帧，x 900, y -300, 车身角度 0，车轮角度 0
		20, 60,		// 倒车
		5, 30, 255, 0, 262, 1, 7,	// 5, f, x1,x2, y1, y2, n: 5提示；f帧数，x1,x2 圈点中心位置；n提示号。
		10, 65,	// 向右打方向盘120帧
		5, 30, 155, 0, 192, 1, 8,	// 5, f, x1,x2, y1, y2, n: 5提示；f帧数，x1,x2 圈点中心位置；n提示号。
		15, 17,	// 适当回轮
		5, 30, 164, 0, 202, 1, 9,	// 5, f, x1,x2, y1, y2, n: 5提示；f帧数，x1,x2 圈点中心位置；n提示号。
		10, 33,	// 向右打方向盘120帧
		15, 25,		// 向左打方向盘38帧，回正
		20, 32,		// 倒车
		5, 30, 227, 0, 255, 1, 10,	// 5, f, x1,x2, y1, y2, n: 5提示；f帧数，x1,x2 圈点中心位置；n提示号。

		0, 5, 0, 0, 94, 1, 124, 252, 0, 0,	// 设置起始点，30帧，x 0, y 350, 车身角度 -90，车轮角度 0
		22, 42,		// 向前走40帧
		5, 30, 180, 1, 235, 0, 12,	// 5, f, x1,x2, y1, y2, n: 5提示；f帧数，x1,x2 圈点中心位置；n提示号。
		15, 104,		// 向左打方向盘120帧
		10, 25,		// 向右打方向盘38帧，回正
		22, 67,		// 向前走40帧
	];
	var datalen = data.length;	// 数据长度

	// 各命令的长度
	var cmdslen = [10, 0, 0, 0, 0	// 0
	, 7, 0, 0, 0, 0	// 5
	, 2, 0, 0, 0, 0	// 10
	, 2, 0, 0, 0, 0	// 15
	, 2, 0, 2, 0, 0	// 20
	];

	this.start = function () {	// 开始/暂停
		if (timer !== 0) {	// 正在运行
			pause();	// 暂停
			return;
		}

		if (pauseData !== undefined) {	// 恢复现场
			car.x = pauseData.x;
			car.y = pauseData.y;
			car.anglez = pauseData.anglez;
			car.wheelAngle = pauseData.wheelAngle;
			car.speed = pauseData.speed;
			car.turn = pauseData.turn;
			car.turn0 = pauseData.turn0;

			pauseData = undefined;

			if (cmd === 5)	// 如果暂停状态下显示提示，直接跳过
				fram = 0;
		}

		// 显示暂停按钮
		btnGo.style.backgroundPositionY = -80;
		timer = setInterval(run, period);
	}

    //** 在节点上
	function isNode() {
	    return timer === 0 && pauseData === undefined;  // 没有定时器，且不是暂停状态。
	}

    // 开始/暂停
	function pause() {
		if (timer === 0)
			return;

		// 正在运行则暂停
		pauseData = {
			x: car.x,
			y: car.y,
			anglez: car.anglez,
			wheelAngle: car.wheelAngle,
			speed: car.speed,
			turn: car.turn,
			trun0: car.turn0
		};	// 否则暂停
		clearInterval(timer);
		timer = 0;
		// 显示继续按钮
		btnGo.style.backgroundPositionY = 0;
	}

	// 暂停并隐藏提示
	this.pause2 = function () {
		pause();
		
		// 隐藏提示
		if( cmd === 5)
			focu.style.display = "none";
	}

	initpos();
	function initpos() {	// 初始化关键帧列表
		var p = 0;
		while (p - pos0 < datalen) {
			var c = data[p];
			if (c === 0)
				poslist.push(p);

			var len = cmdslen[c];
			if (len === undefined || len === 0)
				throw new Error("Error: command " + c);

			p += len;
		}
	}

	function run() {
		if (fram !== 0) {	// 继续运行本次命令到指定帧数
			fram--;
			if (cmd !== 5)	// 提示状态下不重画
				render();
			return;
		}

		// fram === 0时开始下一条命令
		if (cmd != undefined) {	// 根据刚结束的命令收尾
			switch (cmd) {
				case 5:		// 隐藏提示框
					focu.style.display = "none";
					break;

				case 10:	// 不继续转向
				case 15:
					car.turn = 0;
					break;
			}

			pos += cmdslen[cmd];
		}

		var l = pos - pos0;
		if (l >= datalen) {
			pos = 0;
			cmd = undefined;
			me.stop();
			stepnum = 0;
			objstep.innerHTML = stepprompts[stepnum];
			if (l > datalen)
				throw new Error("Error: data length。");
			else
				return;
		}

		// 新命令
		cmd = data[pos]
		switch (cmd) {
			case 0:		// 定位
				car.x = getint(2);
				car.y = getint(4);
				car.anglez = getint(6) * degree01;
				car.wheelAngle = getint(8) * degree01;
				car.speed = 0;
				car.turn = 0;
				objstep.innerHTML = stepprompts[stepnum++];     // 启动后步骤立即加一
				break;
			case 5:		// 提示
				focu.style.left = getint(2) - 100;	// 圆圈中心x
				focu.style.top = getint(4) - 18;		// 圆圈中心y
				focu.style.display = "block";
				promp.innerHTML = prompts[data[pos + 6]];
				break;
			case 10:	// 左转
				car.turn = -radianframe;
				break;
			case 15:	// 右转
				car.turn = radianframe;
				break;
			case 20:	// 倒车
				car.speed = -speed1;
				break;
			case 22:	// 前进
				car.speed = speed1;
				break;
				//case 255:	// 结束
				//	me.stop();
				//	return;
			default:
				me.stop();
				throw new Error("Error: command " + cmd);
		}
		fram = data[pos + 1];
		//if (fram === 0) {	// 如果帧数是0，直接执行下一条指令。 20140330 fram === 0下一帧直接会执行下一条命令

		//	// ?? 没测试
		//	//pos += cmdslen[cmd];
		//	//setTimeout(run);
		//}

	}

	// 回到定位到上一段
	this.previous = function () {
	    //** 如果不是节点状态步骤-1
	    if (!isNode())
	        stepnum--;

	    this.stop();
		cmd = undefined;
		var le = poslist.length;
		if (pos > poslist[0]) {
			var i = 0;
			for (; i < le && pos >= poslist[i]; i++);	// 找本段开头
			pos = poslist[i - 1];
		}
		else
			pos = poslist[0];	// 第一个
		car.x = getint(2);
		car.y = getint(4);
		car.anglez = getint(6) * degree01;
		car.wheelAngle = getint(8) * degree01;
		car.speed = 0;
		car.turn = 0;

		render();
	}

	// 回到定位到gh 一段
	this.next = function () {
		var le = poslist.length - 1;
		cmd = undefined;
		if (pos < poslist[le]) {	// 如果不是最后一步
			var i = le;
			for (; i >= 0 && pos < poslist[i]; i--);	// 找本段开头
			pos = poslist[i + 1];
			if ( isNode() )	//** 在节点上, 步骤加一，运行和暂停时不加，因为运行时步骤已经加到下一步
			    ++stepnum;
		}
		else {	// 如果是最后一步，到第一步
			pos = poslist[0];
			stepnum = 0;
		}
		objstep.innerHTML = stepprompts[stepnum];
		car.x = getint(2);
		car.y = getint(4);
		car.anglez = getint(6) * degree01;
		car.wheelAngle = getint(8) * degree01;
		car.speed = 0;
		car.turn = 0;
		this.stop();
		render();
	}

	// 停止
	this.stop = function () {
		// 取消暂停状态
		pauseData = undefined;
		fram = 0;	// 暂停状态下 timer 可能是零，所以要在if (timer === 0)之前
		focu.style.display = "none";
	
		if (timer !== 0) {
			clearInterval(timer);
			timer = 0;

			// 显示继续按钮
			btnGo.style.backgroundPositionY = 0;
		}
	}

	// 把两个字节变成一个有符号数
	function getint(i) {
		var b2 = data[pos + i + 1];
		var r = b2 * 0x100 + data[pos + i];
		if (b2 & 0x80) {	// 负数
			r -= 0x10000;
		}
		return r;
	}

}
